export function isNumber(val: unknown): val is number {
    return typeof val === 'number'
}

export function isString(val: unknown): val is string {
    return typeof val ==='string'
}

export function isBoolean(val: unknown): val is boolean {
    return typeof val === 'boolean'
}

export function isArray(val: unknown): val is unknown[] {
    return Array.isArray(val)
}

export function isFunction(val: unknown): val is Function {
    return typeof val === 'function'
}

export function isObject(val: unknown): val is Record<string, unknown> {
    return Object.prototype.toString.call(val) === '[object Object]'
}

export function isInstanceOf(val: unknown, cls: (new(...args: any) => any)): val is InstanceType<typeof cls> {
    return val instanceof cls
}

/**
 * 判断两个类型是否相等。如果 T1 和 T2 是同一个类型，则返回该类型，否则返回 never。
 */
export type IsEqual<T1, T2, Y = T1, N = never> = (<G>() => G extends T1 ? 1 : 2) extends (<G>() => G extends T2 ? 1 : 2)
                                                 ? Y
                                                 : N

/**
 * 获取一个类型的可变属性联合体。
 */
export type MutableKeys<T> = {
    [K in keyof T]: IsEqual<{ [Q in K]: T[K] }, { -readonly [Q in K]: T[K] }, K>
}[keyof T]

/**
 * 获取一个类型的只读属性联合体。
 */
export type ReadonlyKeys<T> = {
    [K in keyof T]: IsEqual<{ [Q in keyof K]: T[K] }, { -readonly [Q in keyof K]: T[K] }, never, K>
}[keyof T]

/**
 * 返回只包含可变属性的类型副本。
 */
export type RemainMutable<T> = Pick<T, MutableKeys<T>>

/**
 * 返回只包含只读属性的类型副本。
 */
export type RemainReadonly<T> = Pick<T, ReadonlyKeys<T>>

/**
 * 返回过滤掉成员方法的类型副本。
 */
export type FilterFunctions<T> = Pick<T, { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]>